#pragma once
#include "BlueprintScriptLibrary/Pin.h"
#include "BlueprintScriptLibrary/Var.h"
#include "BlueprintScriptLibrary/RegistAction.h"
#include "base/Utility.h"
#include <BlueprintScriptLibrary/VariableEntity.h>
using namespace BlueprintScriptLibrary;
class PrintFunc : public FunctionPin
{
public:
    PrintFunc() {
        name = "Print";
        Inputs = (IVariableEntity***)new unsigned int[1];
        next = nullptr;
    }
    ~PrintFunc() {
        delete[]Inputs;
    }
    void Execute()
    {
#if _DEBUG
        std::cout << " execute PrintFunc " << std::endl;

        SingleVaribleEntity* sve = dynamic_cast<SingleVaribleEntity*>(*(Inputs[0]));
        if (sve == nullptr)
        {
            printf("Func print error:Inputs format error\r\n");
            return;
        }
        // VarBaseString* vbs = dynamic_cast<VarBaseString*>(sve->data);

        /* if (vbs == nullptr)
         {
             printf("Func print error:Inputs format error\r\n");
             return;
         }*/
        printf("----------------%s\r\n", sve->data->ToString().data());
#else
        if (GetInputParameterNum() > 1) return;
        VarBaseString* par0 = dynamic_cast<VarBaseString*>(*input);
        std::cout << par0->val.data() << std::endl;

#endif
    }
    int GetInputParameterNum() {
        return 1;
    }
    virtual int GetOutputResultNum() { return 0; }
    virtual Pin* GetConnectNextPin() { return nextFP; }
    virtual Pin** GetConnectPin() {
        Pin* p = nextFP;
        return &p;
    }
    void ConnectTo(FunctionPin* fpin) { nextFP = fpin; }
private:
    Var* input[2];
    FunctionPin* nextFP{ nullptr };

};
RegisterBlueprintFunction(PrintFunc);

class AddPinFunc : public FunctionPin
{
public:
    AddPinFunc() :FunctionPin() {
        name = "Add";
        vOut[0] = NewObj<SingleVaribleEntity>();

        Outputs = (IVariableEntity**)vOut;
        Inputs = (IVariableEntity***)new unsigned int[2];
    }
    ~AddPinFunc()
    {
        delete[]Inputs;
    }
    void Execute()
    {
#if _DEBUG
        std::cout << " execute AddPinFunc " << std::endl;
        SingleVaribleEntity* input0 = dynamic_cast<SingleVaribleEntity*>(*(Inputs[0]));
        SingleVaribleEntity* input1 = dynamic_cast<SingleVaribleEntity*>(*(Inputs[1]));
        if (input0 != nullptr && input1 != nullptr)
        {
            VarBaseInt* vb2 = dynamic_cast<VarBaseInt*>(input0->data);
            VarBaseInt* vb1 = dynamic_cast<VarBaseInt*>(input1->data);
            VarBaseInt* vbi = NewObj<VarBaseInt>();
            vbi->val = vb1->val + vb2->val;
            vOut[0]->data = vbi;
            // ((SingleVaribleEntity*)(Outputs[0]))->data
        }
        else {
            printf("Add func execute err: input is nullptr or invalid type\r\n");
        }


#else
        if (GetInputParameterNum() > 2) return;
        VarBaseInt* par0 = dynamic_cast<VarBaseInt*>(*input);
        VarBaseInt* par1 = dynamic_cast<VarBaseInt*>(*(input + 1));
        output[0].val = par0->val + par1->val;
#endif

    }
    virtual void SetInputParameters(Var** para)
    {
        if (para != nullptr)  input[0] = *para;
        if (para + 1 != nullptr)  input[1] = *(para + 1);
    }
    virtual class Var** GetInputParameters() { return nullptr; }
    int GetInputParameterNum() {
        return 2;
    }

    int GetOutputPinNums() override
    {
        return 1;
    }

    Var** GetOutputResult() override
    {
        /* Var* v = output;
         return &v;*/
        return nullptr;
    }
    virtual Pin** GetConnectPin() {
        Pin* p = nextFP;
        return &p;
    }
    virtual Pin* GetConnectNextPin() { return nextFP; }
    void ConnectTo(FunctionPin* fpin) { nextFP = fpin; }
    BlueprintScriptLibrary::Class* GetClass() { return nullptr; }
private:
    // VarBaseInt output[1]{ 0 };
    Var* input[2];
    FunctionPin* nextFP{ nullptr };
    SingleVaribleEntity* vOut[1];
};
RegisterBlueprintFunction(AddPinFunc)

class HitTestFunc : public FunctionPin
{
public:
    HitTestFunc() {
        name = "HitTest";
        Inputs = (IVariableEntity***)new unsigned int[3];
        IVariableEntity* ive = NewObj<SingleVaribleEntity>();

        Outputs = (IVariableEntity**)(&ive);
    }
    void Execute()
    {
#if _DEBUG
        std::cout << " execute HitTestFunc " << std::endl;
#else
        if (GetInputParameterNum() > 3) return;
        Vec2vbi* par0 = dynamic_cast<Vec2vbi*>(*input);
        Vec2vbi* par1 = dynamic_cast<Vec2vbi*>(*(input + 1));
        Vec2vbi* par2 = dynamic_cast<Vec2vbi*>(*(input + 2));
        output[0] = Utility::HitTest(*par0, *par1, *par2);
#endif
    }
    int GetInputParameterNum() {
        return 3;
    }
    virtual int GetOutputResultNum() { return 1; }
    virtual Pin** GetConnectPin() {
        Pin* p = nextFP;
        return &p;
    }
    virtual Pin* GetConnectNextPin() { return nextFP; }
    void ConnectTo(FunctionPin* fpin) { nextFP = fpin; }
private:
    VarBaseBool output[1]{ 0 };
    Var* input[2];
    FunctionPin* nextFP{ nullptr };
};
RegisterBlueprintFunction(HitTestFunc)


//struct FuncData
//{
//    FunctionPin* fp;
//    FunctionPin* next;
//    int nextId;
//    int id;
//};
class BlueprintFunctionFunc : public FunctionPin
{
public:
    BlueprintFunctionFunc() { name = "BlueprintFunc"; }
    void Execute()
    {
#if _DEBUG
        for (int i = 0;i < funcs.size();i++)
        {
            if (funcs[i].fp != nullptr)
                funcs[i].fp->Execute();
        }
        std::cout << " execute BlueprintFunctionFunc " << std::endl;
#else
        if (GetInputParameterNum() > 3) return;
        Vec2vbi* par0 = dynamic_cast<Vec2vbi*>(*input);
        Vec2vbi* par1 = dynamic_cast<Vec2vbi*>(*(input + 1));
        Vec2vbi* par2 = dynamic_cast<Vec2vbi*>(*(input + 2));
        output[0] = Utility::HitTest(*par0, *par1, *par2);
#endif
    }

    int GetInputParameterNum() {
        return inputNum;
    }
    virtual int GetOutputResultNum() { return outputNum; }
    FunctionPin* FindFunctionPinById(int id) {
        for (int i = 0;i < funcs.size();i++)
        {
            if (funcs[i].id == id)
            {
                return funcs[i].fp;
            }
        }
        return nullptr;
    }
    int inputNum;
    int outputNum;
    std::vector<IVariableEntity*> InputArgs;
    std::vector<IVariableEntity*> OutputResults;

    std::vector<FuncData> funcs;
};
RegisterBlueprintFunction(BlueprintFunctionFunc)